//
//  LXMoyaResultSerializer.swift
//  LXMoyaHelper
//
//  Created by yoctech on 2021/8/5.
//

import Foundation
import Moya


/// Moya.Response到指定Model的转换器,可以自定义处理转换过程,并在转换时处理服务器返回的错误码
/// 比如请求成功了,但是服务器返回的code是失败,那么可以在转换过程中,把本次请求的Result,指向failure case,
public protocol LXMoyaResultSerializer: Any {

    func serialize<T:LXJsonMapper >(response: Moya.Response) throws -> T
    func serializeArray<T:LXJsonMapper >(response: Moya.Response) throws -> [T]
    func serialize<T:LXJsonMapper >(result: Result<Moya.Response, MoyaError>) -> Result<T, LXError>
    func serializeArray<T:LXJsonMapper >(result: Result<Moya.Response, MoyaError>) -> Result<[T], LXError>

} 

public extension LXMoyaResultSerializer {
    func serializeArray<T: LXJsonMapper>(result: Result<Response, MoyaError>) -> Result<[T], LXError> {
        switch result {
        case .success(let resp):
            do {
                let models: [T] = try self.serializeArray(response: resp)
                return .success(models)
            } catch let err {
                if let error = err as? MoyaError {
                    return .failure(error.lxerror)
                }
                return .failure(err as? LXError ?? .objectMapping(err, resp))
            }
        case .failure(let err):
            return .failure(err.lxerror)
        }
    }
    
    func serialize<T:LXJsonMapper >(result: Result<Moya.Response, MoyaError>) -> Result<T, LXError> {
        switch result {
        case .success(let resp):
            do {
                let model: T =  try self.serialize(response: resp)
                return .success(model)
            } catch let err {
                if let error = err as? MoyaError {
                    return .failure(error.lxerror)
                }
                return .failure(err as? LXError ?? .objectMapping(err, resp))
            }
        case .failure(let err):
            return .failure(err.lxerror)
        }
    }

}

public struct LXMoyaResultSerializeNormal: LXMoyaResultSerializer {
    
    public func serialize<T:LXJsonMapper >(response: Moya.Response) throws -> T {
        do {
            let model: T =  try response.mapObject(T.self)
            return model
        } catch let err {
            if let error = err as? MoyaError {
                throw error.lxerror
            }else {
                throw LXError.objectMapping(err, response)
            }
        }
    }
    
    public func serializeArray<T:LXJsonMapper >(response: Moya.Response) throws -> [T] {
        do {
            let models: [T] =  try response.mapArray(T.self)
            return models
        } catch let err {
            if let error = err as? MoyaError {
                throw error.lxerror
            }else {
                throw LXError.objectMapping(err, response)
            }
        }
    }

}

public extension MoyaError {
    var lxerror: LXError {
        switch self {
        case .imageMapping(let resp):
            return .imageMapping(resp)
        case .jsonMapping(let resp):
            return .jsonMapping(resp)
        case .stringMapping(let resp):
            return .stringMapping(resp)
        case .objectMapping(let err, let resp):
            return .objectMapping(err, resp)
        case .encodableMapping(let err):
            return .encodableMapping(err)
        case .statusCode(let resp):
            return .statusCode(resp)
        case .underlying(let err, let resp):
            return .underlying(err, resp)
        case .requestMapping(let str):
            return.requestMapping(str)
        case .parameterEncoding(let err):
            return .parameterEncoding(err)
        default:
            return .other(70006, message: "Moya未知错误")
        }
    }
}

